package com.conradharrison.example.simplecamera;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.OnScanCompletedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.conradharrison.example.simplecamera.R.id;

public class MainActivity extends Activity implements OnClickListener{

    private Camera mCamera;
    private CameraPreview mPreview;
    private int cameraId = 0; 
    private boolean takePictureDone = true;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    	
        Log.v("Conrad", "Camera.onCreate called");

    	super.onCreate(savedInstanceState);
        
    	setContentView(R.layout.activity_main);

        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this);
        FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
        preview.addView(mPreview, LayoutParams.MATCH_PARENT);
        
        // Add a listener to the Capture button
        Button captureButton = (Button) findViewById(id.capture_button);
        captureButton.setOnClickListener(this);        

        // Add a listener to the switch button
        Button switchButton = (Button) findViewById(id.switch_button);
        switchButton.setOnClickListener(this);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void onHelpClick(MenuItem item) {
    	switch (item.getItemId()) {
    	case R.id.Help:
    		Intent intent = (new Intent(this, HelpTextActivity.class));
    		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    		startActivity (intent);
    		break;
    	default:
    		break;
    	}
    }
    
    @Override
    protected void onPause() {
    	
        Log.v("Conrad", "Camera.onPause called");

        super.onPause();
        
    	Log.v("Conrad", "Clearing previewCallback");        
		mCamera.setPreviewCallback(null);
        stopPreviewAndReleaseCamera();
    }

    @Override
    protected void onResume() {
    	
        Log.v("Conrad", "Camera.onResume called");
        
        super.onResume();        
        openCameraAndSetPreview();
        
    	Log.v("Conrad", "Setting previewCallback");        
		mCamera.setPreviewCallback(MyPreviewCallback);
    }
    

    @Override
    public void onClick(View v) {
        
        Button captureButton = (Button) findViewById(id.capture_button);
        Button switchButton = (Button) findViewById(id.switch_button);
        
        if( captureButton.getId() == ((Button)v).getId() ){
            
        	if (takePictureDone) {
        		takePictureDone = false;
            	mCamera.takePicture(MyShutterCallback, RawPictureCallback, PostViewPictureCallback, JpegPictureCallback);
        	}
        	
            Log.v("Conrad", "takePicture() done");
        }
        else if( switchButton.getId() == ((Button)v).getId() ){
            stopPreviewAndReleaseCamera();
        	cameraId = (cameraId == 0 ? 1 : 0);
            openCameraAndSetPreview();
        }
        
    }

    private void writeData(byte[] data, String filename) {
        File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/simplecamera");
        if (!folder.exists()) {
            folder.mkdirs();
        }
        Log.v("Conrad", "Writing File name : " + folder+"/"+filename);
        try{
            File out = new File(folder,filename);
            out.createNewFile();
            DataOutputStream fo = null;

            fo = new DataOutputStream( new FileOutputStream(out));
            fo.write(data);
            fo.close();
            
            MediaScannerConnection.scanFile(
      		      getApplicationContext(), 
      		      new String[]{out.getAbsolutePath()}, 
      		      null, 
      		      new OnScanCompletedListener() {
      		         @Override
      		         public void onScanCompleted(String path, Uri uri) {
      		            Log.v("Conrad", "file " + path + " was scanned successfully: " + uri);
      		         }
      		      });

	    } catch (FileNotFoundException e) {
	        e.printStackTrace();
	    } catch (IOException e) {
	        e.printStackTrace();
	    } catch (Exception e){
            e.printStackTrace();
        }

    }
    
    private ShutterCallback MyShutterCallback = new ShutterCallback() {
        @Override
        public void onShutter() {
            TextView tv = (TextView) findViewById(id.textView1);
            tv.setText("shuttertime: "+System.currentTimeMillis());
            Log.v("Conrad","shuttertime: "+System.currentTimeMillis());
        }
    };
    
    private PictureCallback RawPictureCallback = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            TextView tv = (TextView) findViewById(id.textView2);
            tv.setText("rawtime: "+System.currentTimeMillis()+","+data);
            Log.v("Conrad","rawtime: "+System.currentTimeMillis()+","+data);
        }
    };

    private PictureCallback PostViewPictureCallback = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            TextView tv = (TextView) findViewById(id.textView3);
            tv.setText("postviewtime: "+System.currentTimeMillis()+","+data);
            Log.v("Conrad","postviewtime: "+System.currentTimeMillis()+","+data);
            
            for (int i=0; i<100; i++) {
            		data[i] = (byte) ~data[i];
            }

            String filename = String.format(Locale.getDefault(), "%d-post.jpg", System.currentTimeMillis());
        	writeData(data, filename);

            Log.d("Conrad", "PostViewPictureCallback - Wrote bytes: " + data.length);
        }
    };
    
    private PictureCallback JpegPictureCallback = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            TextView tv = (TextView) findViewById(id.textView4);
            tv.setText("jpegtime: "+System.currentTimeMillis()+","+data);
            Log.v("Conrad","jpegtime: "+System.currentTimeMillis()+","+data);
            
            String filename = String.format(Locale.getDefault(), "%d-jpeg.jpg", System.currentTimeMillis());
        	writeData(data, filename);

        	Log.d("Conrad", "JpegPictureCallback - Wrote bytes: " + data.length);

            mCamera.startPreview();
            takePictureDone = true;
        }        
    };

    private PreviewCallback MyPreviewCallback = new PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
        	Log.v("Conrad", "Inside previewCallback"+camera);       
            ((TextView)findViewById(id.textView5)).setText("previewtime: "+System.currentTimeMillis()+","+data);
            Log.v("Conrad","previewtime: "+System.currentTimeMillis()+","+data);

        }        
    };
   
    private void setCameraDisplayOrientation() {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        mCamera.setDisplayOrientation(result);
    }

    private void openCameraAndSetPreview()
    {
        try {
            mCamera = Camera.open(cameraId);            
        } catch (Exception e) {
            Log.e(getString(R.string.app_name), "openCameraAndSetPreview() failed to open camera");
            e.printStackTrace();
        }  
        
        setCameraDisplayOrientation();
        
        try {
            mCamera.setPreviewDisplay(mPreview.getHolder());
        } catch (IOException e) {
            Log.d("Conrad", "openCameraAndSetPreview() Error setting camera preview: " + e.getMessage());
        }
		mCamera.startPreview();
		mPreview.mCamera = mCamera;
    }
    
    private void stopPreviewAndReleaseCamera() {  	
		mCamera.stopPreview();
		mCamera.release();
		mPreview.mCamera = null;
    }
    
}



